#![no_std]
#![allow(unused)]
#![feature(core_intrinsics)]
#![feature(stdsimd)]
#![feature(offset_of)]
#![feature(offset_of_enum)]
#![feature(lazy_cell)]

use core::intrinsics::unlikely;

use bitflags::bitflags;
use global::get_page_from_freelist;
use page::Page;
use zone::{ZoneType, MAX_ORDER};

mod addrspace;
pub use addrspace::pagedef::*;
mod error;
mod global;
mod memblock;
mod page;
mod zone;

bitflags! {
    #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
    pub struct GfpFlags: u32 {
        const DMA         = 0b0000001;
        const NORMAL      = 0b0000010;
        const ZERO        = 0b0000100;
    }
}

#[inline]
pub fn free_the_pages(page: &'static mut Page, order: usize) {
    if order == 0 {
        page.free_unref_page();
    } else {
        page.free_pages_ok(order);
    }
}

pub fn alloc_pages(gfp_mask: GfpFlags, order: usize) -> Option<&'static mut Page> {
    if unlikely(order >= MAX_ORDER) {
        return None;
    }

    let index = if gfp_mask.contains(GfpFlags::NORMAL) {
        ZoneType::Normal
    } else {
        ZoneType::Dma
    };

    let res = get_page_from_freelist(gfp_mask, order, index)?;
    unsafe { Some(res.as_mut().unwrap()) }
}

pub fn get_free_pages(gfp_mask: GfpFlags, order: usize) -> usize {
    order
}

#[inline(always)]
pub fn get_free_page(gfp_mask: GfpFlags) -> usize {
    get_free_pages(gfp_mask, 0)
}
